#include <string>
#include "database.h"
#include "memdatabase.h"
#include <map>
#include <iostream>
#include <iterator>
using namespace std;


typedef unsigned int entry_id;
typedef string group_name;
typedef map<entry_id, news_entry> news_group;
typedef map<group_name, news_group> database;

//new typedefs for groupid
typedef unsigned int group_id;
typedef set<group_id> group_ids;
typedef map<group_name, group_id> idmap;
typedef map<group_id, group_name> idmapinv;

memdatabase::memdatabase():current_article_id(1) {}
memdatabase::~memdatabase(){}

bool memdatabase::create_newsgroup(string group) {
	database::iterator it = db.find(group);
	db[group];
	
	group_id new_id = ids.size(); //never empty this container.
	ids.insert(new_id);
	idm.insert(pair<group_name, group_id>(group, new_id));
	idminv.insert(pair<group_id, group_name>(new_id, group));
	
	if ( it != db.end())
		return false;
	return true;
}	

/* Creates a news entry.*/

pair<bool, unsigned int> memdatabase::put(const unsigned int group, const string title, const string author, const string text){
	idmapinv::iterator it = idminv.find(group);
	if(it == idminv.end() || title.size()==0 || author.size()==0 || text.size() == 0){
		return make_pair<bool, unsigned int>(false, 0);
	}
	string group_s = it -> second;
	news_entry e;
	e.title = title;
	e.author = author;
	e.text = text;
	//news_group g = db.find(group_s)->second; // för att nedatstående krånglia kod ska funka.
	//cout << "size of group " << group << " is " << db.find(group_s)->second.size() << " article id:" << current_article_id <<endl; 
	db.find(group_s)->second.insert(make_pair<unsigned int, news_entry>(current_article_id, e));
	return make_pair<bool, unsigned int>(true, current_article_id++);
}


pair<int, map<string, string> > memdatabase::get(const unsigned int group_id, const unsigned int article_id) {
	idmapinv::iterator it = idminv.find(group_id);
	map<string, string> m;
	if(it == idminv.end()) {
		return make_pair<int, map<string, string> >(1, m);
	}
	string group_s = it -> second;
	database::iterator db_iter = db.find(group_s);
	news_group::iterator ng_iter = db_iter->second.find(article_id);
	if(ng_iter == db_iter->second.end())
		return make_pair<int, map<string, string> >(2, m);
	news_entry ne = ng_iter->second;	
	m["title"] = ne.title;
	m["author"] = ne.author;
	m["text"] = ne.text;
	return make_pair<int, map<string, string> >(0, m);
}


vector<pair<unsigned int, string> > memdatabase::get_newsgroups() {
	vector<pair<unsigned int, string> > v;
	database::iterator it = db.begin();
	while(it != db.end()){
		v.push_back(make_pair<unsigned int, string>(idm.find(it->first)->second, it->first));
		++it;
	}
	return v;
}


bool memdatabase::remove_newsgroup(const unsigned int group_id) {
	idmapinv::iterator it = idminv.find(group_id);
	if(it == idminv.end()) {
		return false;
	}
	string group_s = it -> second;
	idminv.erase(it);
	database::iterator iter = db.find(group_s);
	return (db.erase(iter), true);
}


vector<pair<unsigned int, string> > memdatabase::get_news_entries(unsigned int group){
	vector<pair<unsigned int, string> > v;
	idmapinv::iterator it = idminv.find(group);
	if(it == idminv.end()){
		v.push_back(make_pair<unsigned int, string>(0, ""));
		return v;
	}
	string group_s = it -> second;
	news_group g = db.find(group_s)->second;
	news_group::iterator iter = g.begin();
	for(; iter != g.end(); iter++){
		v.push_back(make_pair<unsigned int, string>(iter->first, iter->second.title));
	}
	return v;
}

int memdatabase::remove(const unsigned int group_id, const unsigned int article_id) {
	idmapinv::iterator it = idminv.find(group_id);
	if(it == idminv.end()) {
		return 1;
	}
	string group_s = it -> second;
	database::iterator db_iter = db.find(group_s);
	news_group::iterator ng_iter = db_iter->second.find(article_id);
	if(ng_iter == db_iter->second.end())
		return 2;
	db_iter->second.erase(ng_iter);
	return 0;
}


/* Removes a news entry.*/
 /*bool memdatabase::remove(const string group, const string id) {
	database::iterator iter = db.find(group);
	if(iter == db.end())
		return false;
	news_group::iterator ng_iter = iter->second.find(id);
	if(ng_iter == iter->second.end())
		return false;
	return (iter->second.erase(ng_iter), true);
}*/


